#if !defined(__Gomoku_GomokuBitmask_h)
#define __Gomoku_GomokuBitmask_h

/******************- Define -*******************/

#define EMPTY		0
#define WHITE		1
#define ISNTEMPTY	536870912

/* Horizontal */

#define UPH			2 /* One neighbor */
#define DPH			6 /* Two neighbor */
#define TPH			14 /*Three neighbor*/
#define QPH			30 /* four neighbor */
#define CPH			62 /* five or more neighbor */

#define TLH			64 /* Ennemy in line on the top */
#define TRH			128 /* Ennemy in line on the bot */

#define TAKENMASKH	198
#define TOTALH		254

#define NBUH(x) (((x & UPH) == UPH) ? 1 : 0)
#define NBDH(x) (((x & DPH) == DPH) ? 2 : NBUH(x))
#define NBTH(x) (((x & TPH) == TPH) ? 3 : NBDH(x))
#define NBQH(x) (((x & QPH) == QPH) ? 4 : NBTH(x))
#define NBH(x)	(((x & CPH) == CPH) ? 5 : NBQH(x))

#define MKUH(x)	(x == 1 ? UPH : 0)
#define MKDH(x)	(x == 2 ? DPH : MKUH(x))
#define MKTH(x) (x == 3 ? TPH : MKDH(x))
#define MKQH(x) (x == 4 ? QPH  : MKTH(x))
#define MKH(x)	(x >= 5 ? CPH : MKQH(x))

/* Vertical */

#define UPV			256 /* One neighbor */
#define DPV			768 /* Two neighbor */
#define TPV			1792 /*Three neighbor*/
#define QPV			3840 /* four neighbor */
#define CPV			7936 /* five or more neighbor */

#define TLV			8192 /* Ennemy in line on the left */
#define TRV			16384 /* Ennemy in line on the right */

#define TAKENMASKV	25344
#define TOTALV		32512

#define NBUV(x) (((x & UPV) == UPV) ? 1 : 0)
#define NBDV(x) (((x & DPV) == DPV) ? 2 : NBUV(x))
#define NBTV(x) (((x & TPV) == TPV) ? 3 : NBDV(x))
#define NBQV(x) (((x & QPV) == QPV) ? 4 : NBTV(x))
#define NBV(x)	(((x & CPV) == CPV) ? 5 : NBQV(x))

#define MKUV(x)	(x == 1 ? UPV : 0)
#define MKDV(x)	(x == 2 ? DPV : MKUV(x))
#define MKTV(x) (x == 3 ? TPV : MKDV(x))
#define MKQV(x) (x == 4 ? QPV : MKTV(x))
#define MKV(x)	(x >= 5 ? CPV : MKQV(x))


/* Diagonal North South \ */

#define UPDNS		32768 /* One neighbor */
#define DPDNS		98304 /* Two neighbor */
#define TPDNS		229376 /*Three neighbor*/
#define QPDNS		491520 /* four neighbor */
#define CPDNS		1015808 /* five or more neighbor */

#define TLDNS		1048576 /* Ennemy in line on the left */
#define TRDNS		2097152 /* Ennemy in line on the right */

#define TAKENMASKDNS	3244032
#define TOTALDNS	4161536

#define NBUDNS(x)	(((x & UPDNS) == UPDNS) ? 1 : 0)
#define NBDDNS(x)	(((x & DPDNS) == DPDNS) ? 2 : NBUDNS(x))
#define NBTDNS(x)	(((x & TPDNS) == TPDNS) ? 3 : NBDDNS(x))
#define NBQDNS(x)	(((x & QPDNS) == QPDNS) ? 4 : NBTDNS(x))
#define NBDNS(x)	(((x & CPDNS) == CPDNS) ? 5 : NBQDNS(x))

#define MKUDNS(x)	(x == 1 ? UPDNS : 0)
#define MKDDNS(x)	(x == 2 ? DPDNS : MKUDNS(x))
#define MKTDNS(x)	(x == 3 ? TPDNS : MKDDNS(x))
#define MKQDNS(x)	(x == 4 ? QPDNS : MKTDNS(x))
#define MKDNS(x)	(x >= 5 ? CPDNS : MKQDNS(x))

/* Diagonal South North / */

#define UPDSN		4194304 /* One neighbor */
#define DPDSN		12582912 /* Two neighbor */
#define TPDSN		29360128 /*Three neighbor*/
#define QPDSN		62914560 /* four neighbor */
#define CPDSN		130023424 /* five or more neighbor */

#define TLDSN		134217728 /* Ennemy in line on the left */
#define TRDSN		268435456 /* Ennemy in line on the right */

#define TAKENMASKDSN 415236096
#define TOTALDSN	532676608

#define NBUDSN(x)	(((x & UPDSN) == UPDSN) ? 1 : 0)
#define NBDDSN(x)	(((x & DPDSN) == DPDSN) ? 2 : NBUDSN(x))
#define NBTDSN(x)	(((x & TPDSN) == TPDSN) ? 3 : NBDDSN(x))
#define NBQDSN(x)	(((x & QPDSN) == QPDSN) ? 4 : NBTDSN(x))
#define NBDSN(x)	(((x & CPDSN) == CPDSN) ? 5 : NBQDSN(x))

#define MKUDSN(x)	(x == 1 ? UPDSN : 0)
#define MKDDSN(x)	(x == 2 ? DPDSN : MKUDSN(x))
#define MKTDSN(x)	(x == 3 ? TPDSN : MKDDSN(x))
#define MKQDSN(x)	(x == 4 ? QPDSN : MKTDSN(x))
#define MKDSN(x)	(x >= 5 ? CPDSN : MKQDSN(x))

/******************- Macro -*******************/

#define INITPIECE	4227330

#define CHECKMASK(x,y)	((x & y) == y ? true : false)

#define TripleisBlockedH(x) ((x & TOTALH) > DPH ? true : false)
#define TripleisBlockedV(x) ((x & TOTALV) > DPV ? true : false)
#define TripleisBlockedDNS(x) ((x & TOTALDNS) > DPDNS ? true : false)
#define TripleisBlockedDSN(x) ((x & TOTALDSN) > DPDSN ? true : false) 

#define isOpposite(x, y) ((((x == 0 && ((y & WHITE) != WHITE)) || (x == 1 && ((y & WHITE) == WHITE))) && y != 0) ? true : false)
#endif